package com.ailot.cloud.base.security.utils;


import cn.hutool.core.util.StrUtil;
import com.ailot.cloud.base.common.constants.SecurityConstant;
import com.ailot.cloud.base.common.exception.BizException;
import com.ailot.cloud.base.security.model.JwtUser;
import lombok.experimental.UtilityClass;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

;

/**
 * 安全工具类
 * <p>
 * 注意有两种认证信息
 * 一种是正常用户携带的
 * 不接受获取匿名用户的 如果是匿名用户调用 直接算作空
 * <p>
 * 另一种是匿名用户携带的
 * 调用 default 相关接口的。则是可以接受获取匿名用户的
 */
@UtilityClass
public class SecurityUtil {


    /**
     * 获取Authentication
     * <p>
     * 前置条件判断
     * 如果不是登录用户 就必须要 匿名用户
     * 否则是非法调用！！
     */
    public Authentication getAuthentication() {
        return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
                // 如果没有任何认证信息 非法用户
                .orElseThrow(() -> new AuthenticationCredentialsNotFoundException("非法用户访问!!!"));
    }

    /**
     * 是否是匿名用户调用
     *
     * @return 判断结果
     */
    public Boolean isAnonymous() {
        return getAuthentication() instanceof AnonymousAuthenticationToken;
    }


    /**
     * 获取用户
     */
    public Optional<JwtUser> getUser() {
        return Optional.ofNullable(getAuthentication()).map(Authentication::getPrincipal).map(p -> p instanceof Jwt ? JWTUtil.principalFrom((Jwt) p) : null);
    }

    /**
     * 获取用户角色信息
     *
     * @return 角色集合
     */
    public List<String> getRoles() {
        return Optional.ofNullable(getAuthentication()).map(Authentication::getAuthorities).orElse(new ArrayList<>()).stream().filter(granted -> StrUtil.startWith(granted.getAuthority(), SecurityConstant.ROLE)).map(granted -> StrUtil.removePrefix(granted.getAuthority(), SecurityConstant.ROLE)).map(String::valueOf).collect(Collectors.toList());
    }

    /**
     * 获取用户id
     *
     * @return 用户不存在就是null
     */
    @Nullable
    public String getId() {
        // 匿名算作空
        if (isAnonymous()) {
            return null;
        }
        return getUser().map(JwtUser::getId).orElse(null);
    }


    /**
     * 获取用户ID
     *
     * @return 用户ID 如果获取不到使用默认值 默认系统内部用户
     */
    public String getIdOrDefault() {
        return getUser().map(JwtUser::getId).orElseThrow(() -> new BizException("用户调用信息异常"));
    }

    /**
     * 部门id
     */
    @Nullable
    public String getOrgId() {
        // 匿名算作空
        if (isAnonymous()) {
            return null;
        }
        return getUser().map(JwtUser::getOrgId).orElse(null);
    }


    /**
     * 用户名
     */
    @Nullable
    public String getUsername() {
        // 匿名算作空
        if (isAnonymous()) {
            return null;
        }

        return getUser().map(JwtUser::getUsername).orElse(null);
    }

    public String getUsernameOrDefault() {
        return getUser().map(JwtUser::getUsername).orElseThrow(() -> new BizException("用户调用信息异常"));
    }


}
